﻿/*
 * Created by: 
 * Created: Friday, April 20, 2007
 */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Web.UI;
using Dune.Common.ControlFlow;
using Dune.Common.DataUtils;
using Dune.Common.TextTemplates.Exceptions;
using Dune.Common.Utils;

namespace Dune.Common.TextTemplates.Impl.ASPNET
{
    public class ParametersBinder
    {
        public ICollection<TemplateParametrInfo> GetParameters(Type templateType)
        {
            if (templateType == null)
                throw new ArgumentException("templateType");

            List<TemplateParametrInfo> ret = new List<TemplateParametrInfo>();


            ICollection<MemberInfo> infos = GetParametersMembers(templateType);

            foreach (MemberInfo info in infos)
            {

                string descrition = string.Empty;
                DescriptionAttribute descriptionAttribute =
                    ReflectionUtils.GetFirstAttribure<DescriptionAttribute>(info);
                if (descriptionAttribute != null)
                    descrition = descriptionAttribute.Description;


                Type clrType = null;
                PropertyInfo pi = info as PropertyInfo;
                if (pi != null)
                    clrType = pi.PropertyType;
                else
                {
                    FieldInfo fi = (FieldInfo)info;
                    clrType = fi.FieldType;
                }

                ret.Add(new TemplateParametrInfo(info.Name, descrition, clrType));

            }

            return ret;
        }

        public void Bind(Control control, IDictionary<string, object> templateParams)
        {
            if (control == null)
                throw new ArgumentException("control");

            ICollection<MemberInfo> infos = GetParametersMembers(control.GetType());

            if (templateParams == null)
                return;

            foreach (KeyValuePair<string, object> pair in templateParams)
            {
                MemberInfo info = CollectionsUtils.Find(infos, delegate(MemberInfo obj) { return obj.Name == pair.Key; });
                if (info == null)
                    throw new TextTemplateException("Template parameter with name " + pair.Key + " does not exists");

                try
                {
                    if (info.MemberType == MemberTypes.Field)
                        ReflectionUtils.SetFieldValue(control, info.Name, pair.Value);
                    else
                        ReflectionUtils.SetValue(control, info.Name, pair.Value);
                }
                catch (Exception ex)
                {
                    throw new PrepareTemplateException("Error at binding parametr " + info.Name, ex);
                }
            }
        }

        protected ICollection<MemberInfo> GetParametersMembers(Type templateType)
        {
            if (templateType == null)
                throw new ArgumentException("templateType");

            List<MemberInfo> ret = new List<MemberInfo>();

            MemberInfo[] infos = templateType.GetMembers(BindingFlags.Public | BindingFlags.Instance);

            foreach (MemberInfo info in infos)
            {

                if (!(info.MemberType == MemberTypes.Field || info.MemberType == MemberTypes.Property))
                    continue;

                if (ReflectionUtils.GetFirstAttribure<TemplateParameterAttribute>(info) == null)
                    continue;

                ret.Add(info);

            }

            return ret;
        }
    }
}